package xzk

import (
	"errors"
	"fmt"
	"sync"
	"time"

	"github.com/samuel/go-zookeeper/zk"
)

type Config struct {
	Servers     []string      `yaml:"servers"`
	ConnTimeout time.Duration `json:"connTimeout"`
}

type Pool struct {
	config       *Config
	zKClientConn *zk.Conn
}

var pool = new(Pool)
var once = &sync.Once{}

func Init(conf *Config) {
	once.Do(func() {
		pool = &Pool{
			config:       conf,
			zKClientConn: nil,
		}

		if err := pool.initConnection(); err != nil {
			fmt.Println("initConnection err: " + err.Error())
		}
	})
}

func (p *Pool) isConnected() bool {
	if p.zKClientConn == nil {
		return false
	}

	if p.zKClientConn.State() != zk.StateConnected {
		return false
	}

	return true
}

func (p *Pool) initConnection() error {
	if !p.isConnected() {
		conn, connChan, err := zk.Connect(p.config.Servers, p.config.ConnTimeout)
		if err != nil {
			fmt.Println("zk Connect err: " + err.Error())
			return err
		}

		for {
			isConnected := false
			select {
			case connEvent := <-connChan:
				if connEvent.State == zk.StateConnected {
					isConnected = true
					fmt.Println("connect to zookeeper server success!")
				}
			case _ = <-time.After(time.Second * 3): // 3秒仍未连接成功则返回连接超时
				return errors.New("connect to zookeeper server timeout")
			}

			if isConnected {
				p.zKClientConn = conn
				break
			}
		}
	}

	return nil
}
